/*****************************************************************************
 * 
 * Copyright [2013] [Mervin.Wong]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 *       
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *  
 *****************************************************************************/
package util;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;


import base.Global.NodeIdType;
import base.Global.NumberType;

/**
 *@name MathTool.java
 *@description  常用数学工具类
 *@author 王进法<Mervin.Wong>
 *@version 
 *@Date 2013-1-15上午10:07:13
 */
public class MathTool {
	public static int seed = 3;
	/**
	 * @name str2Number
	 * @description 节点的ID时int 还是 long
	 * @param NodeIdType nodeIdType
	 * @param Strong numStr
	 * @return Number
	 */
	public static Number str2Number(NodeIdType nodeIdType, String numStr){
		if(nodeIdType == NodeIdType.LONG){
			return Long.parseLong(numStr);
		}else{
			return Integer.parseInt(numStr);
		}
	}
	
	/**
	 * @name str2Num
	 * @description 将字符串转换成指定基本类型的数
	 * @param numType
	 * @param numStr
	 * @return
	 */
	public static Number str2Num(NumberType numType, String numStr){
		if(numType.equals(NumberType.LONG)){
			return Long.parseLong(numStr);
		} else if (numType.equals(NumberType.FLOAT)) {
			return Float.parseFloat(numStr);
		} else {
			return Integer.parseInt(numStr);
		}
	}
	/**
	 * @name ip2Int
	 * @description ip地址转换成Long整型的数
	 * @param String ipStr
	 * @return long
	 */
	public static long ip2Int(String ipStr){
		String[] ipArr = ipStr.split("\\.");
		return (Long.parseLong(ipArr[0].toString())<<24)+(Long.parseLong(ipArr[1].toString())<<16)+(Long.parseLong(ipArr[2].toString())<<8)+(Long.parseLong(ipArr[3].toString()));
	}
	
	/**
	 * @name ip2Str
	 * @description 将整数的IP地址转换程标准的表示方式 
	 * @param ipInt
	 * @return String
	 */
	public static StringBuilder ip2Str(Long ipInt){
		StringBuilder ipStr = new StringBuilder();
		ipStr.append((ipInt>>24)).append(".").append((ipInt>>16) & 0xFF).append(".").append((ipInt>>8) & 0xFF).append(".").append(ipInt & 0xFF);
		return ipStr;
	}
	/**
	 * @name intersection
	 * @description 两个节点集的交集
	 * @param preSet
	 * @param postSet
	 * @return
	 */
	public static HashSet<Number> intersection(Set<Number> preSet, Set<Number> postSet){
		HashSet<Number> intersection = new HashSet<Number>();
		for (Iterator<Number> iterator = preSet.iterator(); iterator.hasNext();) {
			Number nodeId = (Number) iterator.next();
			if(postSet.contains(nodeId)){
				D.p("intersection:"+nodeId);
				intersection.add(nodeId);
			}
		}
		return intersection;
	}
	/**
	 * @name subtraction
	 * @description 求preSet postSet网络节点集的差集，preSet-postSet
	 * @param preSet
	 * @param postSet
	 * @return
	 */
	public static HashSet<Number> subtraction(Set<Number> preSet, Set<Number> postSet){
		Set<Number> intersection = MathTool.intersection(preSet, postSet);
		HashSet<Number> subtraction = new HashSet<Number>();
		
		for (Iterator<Number> iterator = preSet.iterator(); iterator.hasNext();) {
			Number nodeId = (Number) iterator.next();
			if(!intersection.contains(nodeId)){
				D.p("subtraction:"+nodeId);
				subtraction.add(nodeId);
			}
		}
		return subtraction;
	}
	
	/**
	 * @name frequency
	 * @description 统计degreeMap中相同value数值出现的频数
	 * @param degreeMap
	 * @return
	 */
	public static HashMap<Number, Number> frequency(HashMap<Number, Number> degreeMap){
		HashMap<Number, Number> timesMap = new HashMap<Number, Number>();
		int[] temp = new int[5000];//默认多的最大值可能时1000
		Collection<Number> c = degreeMap.values();
		Number degree = null;
		int degreeMax = 0;
		for (Iterator<Number> iterator = c.iterator(); iterator.hasNext();) {
			
			degree = (Number) iterator.next();
			temp[(Integer) degree]++;
			if(degree.intValue() > degreeMax){
				degreeMax = degree.intValue();
			}
		}
		for (int i = 0; i < temp.length; i++) {
			if(temp[i] > 0){
				timesMap.put(i, temp[i]);
			}
		}
		D.p("degreeMax:"+degreeMax);
		return timesMap;
	}
	public static float average(HashMap<Number, Number> degreeMap){
		int count = 0;
		int totalNodes = 0;
		Collection<Number> c = degreeMap.keySet();
		Number key = null,
				value = null;
		
		for (Iterator<Number> iterator = c.iterator(); iterator.hasNext();) {
			key = (Number) iterator.next();
			value = degreeMap.get(key);
			count += key.intValue()*value.intValue();
			totalNodes += value.intValue();
		}
		return count/(float)totalNodes;
	}
	/**
	 * @name max
	 * @description 集合中的最大值
	 * @param collection
	 * @return
	 */
	public static int max(Collection<Number> collection){
		int max = 0;
		Integer temp = null;
		for (Iterator<Number> iterator = collection.iterator(); iterator.hasNext();) {
			temp = (Integer) iterator.next();
			if(max < temp){
				max = temp;
			}
			
		}
		return max;
	}
	public static int min(Set<Integer> set){
		int min = Integer.MAX_VALUE;
		Integer temp = null;
		for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext();) {
			temp = (Integer) iterator.next();
			if(min > temp){
				min = temp;
			}
		}
		return min;
	}
	/**
	 * @name rate
	 * @description 计算节点的分布频率
	 * @param degreeMap
	 * @return
	 */
	public static HashMap<Number, Number> rate(HashMap<Number, Number> degreeMap){
		HashMap<Number, Number> rateMap = new HashMap<Number, Number>();
		Set<Number> degreeSet = degreeMap.keySet();
		Number degree = 0;
		int totalNode = 0;
		for (Iterator<Number> iterator = degreeSet.iterator(); iterator.hasNext();) {
			 degree= (Number) iterator.next();
			totalNode += degreeMap.get(degree).intValue();
		}
		for (Iterator<Number> iterator2 = degreeSet.iterator(); iterator2.hasNext();) {
			 degree= (Number) iterator2.next();
			 rateMap.put(degree, degreeMap.get(degree).floatValue()/totalNode);
		}
		return rateMap;
	}
	/**
	 * @name random
	 * @description 产生一个0.0~1.0之间的随机数
	 * @return
	 */
	public static float random(){
		float p = 0;
		p = (float) Math.random();
		return p;
	}
	/**
	 * @name random
	 * @description 产生一个min~max之间的随机数
	 * @param min
	 * @param max
	 * @return
	 */
	public static Number random(Number min, Number max){
		Number randNumber = 0;
		Random random = new Random(System.currentTimeMillis());
		randNumber = random.nextInt(max.intValue())%(max.intValue()-min.intValue()+1)+min.intValue();
		return randNumber;
	}
	/**
	 * @name random
	 * @description 产生一个min~max之间的随机数
	 * @param min
	 * @param max
	 * @param nodeIdType
	 * @return
	 */
	public static Number random(Number min, Number max, NodeIdType nodeIdType){
		Number randNumber = 0;
		Random random = new Random(System.currentTimeMillis()+(seed++));
		if(nodeIdType.equals(NumberType.LONG)){
			randNumber = random.nextLong()%(max.longValue()-min.longValue()+1)+min.longValue();
		}else {
			randNumber = random.nextInt(max.intValue())%(max.intValue()-min.intValue()+1)+min.intValue();
		}
		return randNumber;
	}

	public static void main(String[] args){
/*		try {
			BufferedReader reader = new BufferedReader(new FileReader("../data/jfk/deathNodesAdjDegree.txt"));
			BufferedWriter writer = new BufferedWriter(new FileWriter("../data/jfk/deathNodesAdjDegreeRate.txt"));
			HashMap<Integer, Integer> degreeMap = new HashMap<Integer, Integer>();
			HashMap<Integer, Float> rateMap = new HashMap<Integer, Float>();
			StringBuffer str = new StringBuffer();
			String line = new String();
			String[] lineArr = null;
			int[] degreeArr =  new int[1000];
			while((line = reader.readLine())!= null){
				lineArr = line.split("\t");
				//degreeMap.put(Long.parseLong(lineArr[0]),Integer.parseInt(lineArr[1]));
				degreeArr[Integer.parseInt(lineArr[1])]++;
			}
			for (int i = 0; i < degreeArr.length; i++) {
				if(degreeArr[i] > 0){
					degreeMap.put(i, degreeArr[i]);
				}
			}
			rateMap = MathTool.rate(degreeMap);
			Set<Integer> degreeSet = rateMap.keySet();
			for (Iterator<Integer> iterator = degreeSet.iterator(); iterator.hasNext();) {
				Integer integer = (Integer) iterator.next();
				str.append(integer).append("\t").append(rateMap.get(integer)).append("\r\n");
			}
			writer.flush();
			writer.write(str.toString());
			writer.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	*/	
	}
}
